/* 
 * time: 2022-11-07
 * issue: 实现 tic-tac-toe 井字棋
 *
 */
#include<stdio.h>
#include<stdlib.h> // 调用清屏函数

void display(char[3][3]);
int checkWinner(char[3][3]);

// 制作3x3的方格板 board, 填入字符 '1' - '9' 占位 
char board[3][3] = {'1', '2', '3','4', '5', '6', '7', '8', '9'};

int main() {
    int i, player; 
    int choice = 0;
    unsigned int row = 0, column = 0;

    for (i = 0; i < 9; ++i) {
        display(board);
        player = i % 2 + 1; // 当前玩家, 只能 1或2
        
        // 检查方格板, 有3个在一排时 前一个玩家赢
        if (checkWinner(board) != 0) {
            printf("%d 号玩家赢了!\n", (player%2) ? 2 : 1);
            break; 
        }

        do {
            printf(" %d 号玩家开始, 在1-9选一个没被用的数, 存放 %c : ",
                   player, (player == 1) ? 'x' : 'o');
            scanf("%d", &choice);
            getchar(); // 吸收缓冲区回车符

            row = --choice / 3;
            column = choice % 3;
        } while (choice < 0 || choice > 8 || board[row][column] > '9');

        if (player == 1) {
            board[row][column] = 'x';
        } else {
            board[row][column] = 'o';
        }
    } 
    
    getchar(); // 防闪现
    return 0;
}

/* 功能: 显示方格板界面

    样式
     --- --- ---
    | 1 | 2 | 3 |
     --- --- ---
    | 4 | 5 | 6 |
     --- --- ---
    | 7 | 8 | 9 |
     --- --- ---
 */
void display(char board[3][3]) {
    int i, j;
    system("cls");

    puts(" --- --- --- ");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf("| %c ", board[i][j]);
        }
        printf("|\n");
        puts(" --- --- --- ");
    }
}

/* 功能: 检查方格板，有3个在一排的情况

    @return [int] 找到返回1, 没有就返回0
 */
int checkWinner(char board[3][3]) {
    int res = 0; // 返回值, 默认没有
    int i, j;
    for (i = 0; i < 3; i++) {  
        if ((board[i][0] == board[i][1] && board[i][0] == board[i][2]) ||
            (board[0][i] == board[1][i] && board[0][i] == board[2][i])) {
            res = 1; // 查同一行和同一列
            break;
        }
    }
    if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) ||
        (board[0][2] == board[1][1] && board[1][1] == board[2][0])) {
        res = 1; // 查两个斜行
    }
    return res;
}